
#include "service.h"
#include <iostream>
#include <vector>
#define debug 1

using std::cout;
using std::endl;
using std::string;
using std::vector;

void initCheckerboard(vector<Chess> &red, vector<Chess> &black);
bool checkDataValid(const ComData &data);
int changeChessboard(vector<Chess> &red, vector<Chess> &black, const ComData *data);

int main(int argc, char const *argv[])
{
    vector<Chess> red;
    vector<Chess> black;
    if(argc != 2){
        fprintf(stderr, "enter port");
    }
    // 创建监听套接字
    int socketfd = getListen("0.0.0.0", atoi(argv[1]));
    Client client_red(socketfd);
#if debug
    cout << "客户端1 连接通信套接字是：" << client_red.getSocketCom() << endl;
#endif
    Client client_black(socketfd);
#if debug
    cout << "客户端2 连接通信套接字是：" << client_black.getSocketCom() << endl;
#endif

    while (1)
    {
        // 初始化棋盘
        initCheckerboard(red, black);
        bool GameEnd = false;

        // 和客户端确定红黑方阵营
        ComData data_camp = {.type_cmd = Red_cmd};
        client_red.writeClinet(&data_camp, sizeof(ComData));
        data_camp.type_cmd = Black_cmd;
        client_black.writeClinet(&data_camp, sizeof(ComData));

        bool client_red_info_efficacious = false;
        bool client_black_info_efficacious = false;

        while (!GameEnd)
        {
            client_black_info_efficacious=false;
            client_red_info_efficacious=false;
            // 红方走子
            while (!client_red_info_efficacious && !GameEnd)
            {
                ComData *data = reinterpret_cast<ComData *>(client_red.readClinet(sizeof(ComData)));
                switch (data->type_cmd)
                {
                case ChangeChess:
                    if (checkDataValid(*data))
                    {
                        // 有效
                        client_red_info_efficacious = true;
                        int flag = changeChessboard(red, black, data);
                        cout<<"红方 : x"<<data->change.chess.pos.x<<"y "<<data->change.chess.pos.y<<endl;
                        cout<<"红方 :tar_get x "<<data->change.target_pos.x<<" y"<<data->change.target_pos.y<<endl;
                        if (Cat_effectively == flag)
                        {
                            // 走子成功
                            // 向红方发送数据有效
                            ComData data_red_recv = {.type_cmd = Cat_effectively};
                            data_red_recv.change=data->change;
                            client_red.writeClinet(&data_red_recv, sizeof(ComData));
                            // 向黑方发送走子信息,更新黑方本地棋盘
                            client_black.writeClinet(data, sizeof(ComData));
                        }
                        else if (Win == flag)
                        {
                            // 红方取得胜利,
                            ComData data_red_recv = {.type_cmd = Win};
                            // 向红方发送胜利消息
                            client_red.writeClinet(&data_red_recv, sizeof(ComData));

                            data_red_recv.type_cmd = Fail;
                            // 向黑方发送失败消息
                            client_black.writeClinet(&data_red_recv, sizeof(ComData));
                        }
                    }
                    else
                    {
                        // 数据无效，告诉客户端 重新发送，
                        ComData data = {.type_cmd = Cat_uneffectively};
                        client_red.writeClinet(&data, sizeof(ComData));
                    }
                    break;

                default:
                    break;
                }
            }
            
            // 黑方走子
            while (!client_black_info_efficacious && !GameEnd)
            {
                ComData *data = reinterpret_cast<ComData *>(client_black.readClinet(sizeof(ComData)));
                switch (data->type_cmd)
                {
                case ChangeChess:
                    if (checkDataValid(*data))
                    {
                        // 有效
                        client_black_info_efficacious = true;
                        int flag = changeChessboard(black, red, data);
                        cout<<"黑方 : x"<<data->change.chess.pos.x<<"y "<<data->change.chess.pos.y<<endl;
                        cout<<"黑方 :tar_get x "<<data->change.target_pos.x<<" y"<<data->change.target_pos.y<<endl;
                        if (Cat_effectively == flag)
                        {
                            // 走子成功
                            // 向黑方发送数据有效
                            ComData data_red_recv = {.type_cmd = Cat_effectively};
                            data_red_recv.change=data->change;
                            client_black.writeClinet(&data_red_recv, sizeof(ComData));
                            // 向红方发送走子信息,更新红方本地棋盘
                            client_red.writeClinet(data, sizeof(ComData));
                        }
                        else if (Win == flag)
                        {
                            // 黑方取得胜利,
                            ComData data_red_recv = {.type_cmd = Win};
                            // 向红方发送胜利消息
                            client_black.writeClinet(&data_red_recv, sizeof(ComData));

                            data_red_recv.type_cmd = Fail;
                            // 向红方发送失败消息
                            client_red.writeClinet(&data_red_recv, sizeof(ComData));
                        }
                    }
                    else
                    {
                        // 数据无效，告诉客户端 重新发送，
                        ComData data = {.type_cmd = Cat_uneffectively};
                        client_black.writeClinet(&data, sizeof(ComData));
                    }
                    break;

                default:
                    break;
                }
            }
            

            if (GameEnd)
            {
                // 游戏结束
                break;
            }
        }
    }
    return 0;
}

bool checkDataValid(const ComData &data)
{
    return true;
}

int changeChessboard(vector<Chess> &action_camp, vector<Chess> &Waiting_camp, const ComData *data)
{
    Position pos_tmep;

    // 若有重叠则吃掉等待方棋子
    vector<Chess>::iterator position_itr = Waiting_camp.begin();
    for (int i = 0; i < Waiting_camp.size(); i++)
    {
        pos_tmep = Waiting_camp[i].getPosition();
        if (pos_tmep.x == data->change.target_pos.x && pos_tmep.y == data->change.target_pos.y)
        {
            if (Will == Waiting_camp[i].getChessType())
            {
                // 等待方元帅被吃了 —— 游戏结束
                return Win;
            }
            // 吃掉了等待方的这颗棋子
            Waiting_camp.erase(position_itr + i);
            break;
        }
    }
    // 更新行动方当前棋子位置
    for (int i = 0; i < action_camp.size(); i++)
    {
        if (data->change.chess.chess_type == action_camp[i].getChessType())
        {
            action_camp[i].setPosition(data->change.target_pos);
            break;
        }
    }
    return Cat_effectively;
}

void initCheckerboard(vector<Chess> &red, vector<Chess> &black)
{
    red.clear();
    black.clear();

    Position pos = {0, 0};
    // 红棋
    red.push_back(Chess(RED, CarLeft, pos));
    pos = {8, 0};
    red.push_back(Chess(RED, CarRight, pos));
    pos = {1, 0};
    red.push_back(Chess(RED, HorseLeft, pos));
    pos = {7, 0};
    red.push_back(Chess(RED, HorseRight, pos));
    pos = {2, 0};
    red.push_back(Chess(RED, ElephantLeft, pos));
    pos = {6, 0};
    red.push_back(Chess(RED, ElephantRight, pos));
    pos = {3, 0};
    red.push_back(Chess(RED, BachelorLeft, pos));
    pos = {5, 0};
    red.push_back(Chess(RED, BachelorRight, pos));
    pos = {4, 0};
    red.push_back(Chess(RED, Will, pos));

    pos = {1, 2};
    red.push_back(Chess(RED, GunLeft, pos));
    pos = {7, 2};
    red.push_back(Chess(RED, GunRight, pos));

    pos = {0, 3};
    red.push_back(Chess(RED, Redarms1, pos));
    pos = {2, 3};
    red.push_back(Chess(RED, Redarms2, pos));
    pos = {4, 3};
    red.push_back(Chess(RED, Redarms3, pos));
    pos = {6, 3};
    red.push_back(Chess(RED, Redarms4, pos));
    pos = {8, 3};
    red.push_back(Chess(RED, Redarms5, pos));

    // 黑棋
    pos = {0, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, CarLeft, pos));
    pos = {8, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, CarRight, pos));
    pos = {1, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, HorseLeft, pos));
    pos = {7, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, HorseRight, pos));
    pos = {2, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, ElephantLeft, pos));
    pos = {6, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, ElephantRight, pos));
    pos = {3, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, BachelorLeft, pos));
    pos = {5, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, BachelorRight, pos));
    pos = {4, Boundary_max_y - 0};
    black.push_back(Chess(BLACK, Will, pos));

    pos = {1, Boundary_max_y - 2};
    black.push_back(Chess(BLACK, GunLeft, pos));
    pos = {7, Boundary_max_y - 2};
    black.push_back(Chess(BLACK, GunRight, pos));

    pos = {0, Boundary_max_y - 3};
    black.push_back(Chess(BLACK, Redarms1, pos));
    pos = {2, Boundary_max_y - 3};
    black.push_back(Chess(BLACK, Redarms2, pos));
    pos = {4, Boundary_max_y - 3};
    black.push_back(Chess(BLACK, Redarms3, pos));
    pos = {6, Boundary_max_y - 3};
    black.push_back(Chess(BLACK, Redarms4, pos));
    pos = {8, Boundary_max_y - 3};
    black.push_back(Chess(BLACK, Redarms5, pos));
}
